package com.netty.tools;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

public class IPUtils {

	public static String getMACAddress() throws IOException {
		String os = System.getProperty("os.name");

		if (os != null && os.startsWith("Windows"))
			return getWindowsMacAddr();

		if (os != null && os.indexOf("Linux") != -1)
			return getLinuxMacAddr();

		throw new IOException("can not get netinterface mac address, os : " + os);
	}

	/**
	 * 获得机器的第一个IP地址，忽略VMware虚拟的网卡，(忽略127.0.0.1_不行了)
	 * 可能在单机使用，不能忽略127.0.0.1
	 * @return
	 */
	public static String getFirstIPAddress() {
		try {
			Set<String> ipv4Addresses = new HashSet<String>();
			Set<String> ipv6Addresses = new HashSet<String>();

			Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();

			while (interfaces.hasMoreElements()) {

				NetworkInterface item = interfaces.nextElement();

				if (item.getDisplayName().contains("VMware"))
					continue;

				Enumeration<InetAddress> addresses = item.getInetAddresses();
				while (addresses.hasMoreElements()) {
					while (addresses.hasMoreElements()) {
						InetAddress addr = addresses.nextElement();
						if (addr.isLoopbackAddress())
							continue;

						String hostAddress = addr.getHostAddress();
						if (hostAddress.indexOf(':') != -1) {
							ipv6Addresses.add(hostAddress);
						} else {
							ipv4Addresses.add(hostAddress);
						}
					}
				}
			}

			if (ipv4Addresses.size() != 0)
				return ipv4Addresses.iterator().next();

			if (ipv6Addresses.size() != 0)
				return ipv6Addresses.iterator().next();

		} catch (SocketException e) {
			e.printStackTrace();
		}

		return "127.0.0.1";
	}

	/**
	 * 注意，由于java的int是有符号整数，返回值可能是负数。转换的办法如下：
	 * <p>
	 * int ipVal = IPUtils.convertIPAddressToInt("192.168.12.4"); <BR>
	 * long longVal = ipVal & 0xFFFFFFFFL;<BR>
	 * </p>
	 * 
	 * @param ip
	 * @return
	 */
	public static int convertIPAddressToInt(String ip) {
		if (ip == null)
			throw new IllegalArgumentException();

		String[] items = ip.split("\\.");
		if (items.length != 4)
			throw new IllegalArgumentException();

		byte[] bytes = new byte[4];

		bytes[0] = (byte) Integer.parseInt(items[0]);
		bytes[1] = (byte) Integer.parseInt(items[1]);
		bytes[2] = (byte) Integer.parseInt(items[2]);
		bytes[3] = (byte) Integer.parseInt(items[3]);

		return getInt(bytes, 0);
	}
	public static int getInt(byte[] b, int off) {
		return ((b[off + 3] & 0xFF) << 0) + ((b[off + 2] & 0xFF) << 8) + ((b[off + 1] & 0xFF) << 16) + ((b[off + 0] & 0xFF) << 24);
	}
	private static String getLinuxMacAddr() throws IOException {
		final String ADAPTER_MASK = "Link encap:Ethernet";
		final String HW_MASK = "HWaddr";

		String command = "ifconfig -a";
		Process p = Runtime.getRuntime().exec(command);
		BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
		String line;

		List<String> addrList = new ArrayList<String>();

		while ((line = br.readLine()) != null) {
			int p1 = line.indexOf(ADAPTER_MASK);
			if (p1 == -1)
				continue;

			int p2 = line.indexOf("HWaddr", p1 + ADAPTER_MASK.length());

			String address = line.substring(p2 + HW_MASK.length() + 1);

			addrList.add(address);
		}
		br.close();

		if (addrList.size() != 0)
			return addrList.get(0).trim();

		throw new IOException("can not get netinterface mac address");
	}

	private static String getWindowsMacAddr() throws IOException {
		final String ADAPTER_MASK = "Ethernet adapter";

		String command = "cmd.exe /c ipconfig /all";
		Process p = Runtime.getRuntime().exec(command);
		BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
		String line;

		final int VM_ADAPTER = 0;
		final int NORMAL_ADAPTER = 1;

		int stat = NORMAL_ADAPTER;

		List<String> vmMacAddrList = new ArrayList<String>();
		List<String> normalMacAddrList = new ArrayList<String>();

		while ((line = br.readLine()) != null) {
			if (line.startsWith(ADAPTER_MASK)) {
				stat = (line.indexOf("VMware") != -1) ? VM_ADAPTER : NORMAL_ADAPTER;
				continue;
			}

			if (line.indexOf("Physical Address") == -1)
				continue;

			int index = line.indexOf(":");
			index += 2;
			String address = line.substring(index);

			if (address == null)
				continue;

			address = address.trim();
			address = address.replace('-', ':'); // 转为和linux表示法一致

			switch (stat) {
			case VM_ADAPTER:
				vmMacAddrList.add(address);
				break;
			default:
				normalMacAddrList.add(address);
				break;
			}
		}
		br.close();

		if (normalMacAddrList.size() != 0)
			return normalMacAddrList.get(0);

		if (vmMacAddrList.size() != 0)
			return vmMacAddrList.get(0);

		throw new IOException("can not get netinterface mac address");
	}

	public static void main(String[] args) throws Exception {
		System.out.println(getMACAddress());
	}

	public static boolean constainsIP(String text) {
		return constainsIP(text, new StringBuffer());
	}

	public static boolean constainsIP(String text, StringBuffer output) {

		StringBuffer digit0 = new StringBuffer();
		StringBuffer digit1 = new StringBuffer();
		StringBuffer digit2 = new StringBuffer();
		StringBuffer digit3 = new StringBuffer();
		int pos = 0;
		for (;;) {
			digit0.delete(0, digit0.length());
			digit1.delete(0, digit1.length());
			digit2.delete(0, digit1.length());
			digit3.delete(0, digit1.length());

			int p0 = text.indexOf('.', pos);

			if (p0 == -1)
				return false;

			for (int i = p0 - 1; i >= 0; --i) {
				char ch = text.charAt(i);
				if (!Character.isDigit(ch)) {
					break;
				}
				digit0.append(ch);
			}
			if (digit0.length() == 0) {
				pos = p0 + 1;
				continue;
			}

			int p1 = text.indexOf('.', p0 + 1);

			if (p1 == -1) {
				pos = p0 + 1;
				continue;
			}

			for (int i = p0 + 1; i < p1; ++i) {
				char ch = text.charAt(i);
				if (!Character.isDigit(ch)) {
					digit1.delete(0, digit1.length());
					break;
				}
				digit1.append(ch);
			}

			if (digit1.length() == 0) {
				pos = p0 + 1;
				continue;
			}

			// / p2
			int p2 = text.indexOf('.', p1 + 1);

			if (p2 == -1) {
				pos = p0 + 1;
				continue;
			}

			for (int i = p1 + 1; i < p2; ++i) {
				char ch = text.charAt(i);
				if (!Character.isDigit(ch)) {
					digit2.delete(0, digit2.length());
					break;
				}
				digit2.append(ch);
			}

			if (digit2.length() == 0) {
				pos = p0 + 1;
				continue;
			}

			// / p3
			for (int i = p2 + 1; i < text.length(); ++i) {
				char ch = text.charAt(i);
				if (!Character.isDigit(ch)) {
					break;
				}
				digit3.append(ch);
			}

			if (digit3.length() == 0) {
				pos = p0 + 1;
				continue;
			}

			output.append(digit0);
			output.append('.');
			output.append(digit1);
			output.append('.');
			output.append(digit2);
			output.append('.');
			output.append(digit3);

			return true;
		}
	}

	/** 
	 * 获取访问用户的客户端IP（适用于公网与局域网）. 
	 */  
	public static final String getIpAddr(final HttpServletRequest request) throws RuntimeException {  
	    if (request == null) {  
	        throw (new RuntimeException("getIpAddr method HttpServletRequest Object is null"));  
	    }  
	    String ipString = request.getHeader("x-forwarded-for");  
	    if (isBlank(ipString) || "unknown".equalsIgnoreCase(ipString)) {  
	        ipString = request.getHeader("Proxy-Client-IP");  
	    }  
	    if (isBlank(ipString) || "unknown".equalsIgnoreCase(ipString)) {  
	        ipString = request.getHeader("WL-Proxy-Client-IP");  
	    }  
	    if (isBlank(ipString) || "unknown".equalsIgnoreCase(ipString)) {  
	        ipString = request.getRemoteAddr();  
	    }  
	  
	    // 多个路由时，取第一个非unknown的ip  
	    final String[] arr = ipString.split(",");  
	    for (final String str : arr) {  
	        if (!"unknown".equalsIgnoreCase(str)) {  
	            ipString = str;  
	            break;  
	        }  
	    }  
	    if(ipString.equals("0:0:0:0:0:0:0:1"))
	    {
	    	ipString = getFirstIPAddress();
	    }
	    return ipString;  
	}
	
	
    public static boolean isBlank(String str) {
        int strLen;
        if (str == null || (strLen = str.length()) == 0) {
            return true;
        }
        for (int i = 0; i < strLen; i++) {
            if ((Character.isWhitespace(str.charAt(i)) == false)) {
                return false;
            }
        }
        return true;
    }
	
}